#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include <sys/socket.h>
#include <arpa/inet.h>  
#include <stdbool.h>    //bool
#include <sys/shm.h>

#include "common.h"
#include "shm_operation.h"
#include "psql_operation.h"




int print_msg(struct Connect_Info*);



int main()
{
    
    struct  Connect_Info connect_info;
    // 创建套接字
    int serv_socket = socket(AF_INET,SOCK_STREAM,0);
    // 定义服务器sock_addr_in结构体
    struct sockaddr_in sin;
    // 结构体赋值
    sin.sin_family=AF_INET;
    // sin.sin_addr.s_addr=inet_addr("127.0.0.1");
    // INADDR_ANY 整个内网
    sin.sin_addr.s_addr=INADDR_ANY;
    sin.sin_port=htons(11234);
    // 绑定套接字及文件符
    int res=bind(serv_socket,(struct sockaddr*) &sin ,sizeof(sin));
    if(res<0)
    {
        printf("bind error!\n");
        return -1;
    }
    // 监听套接字文件符
    res=listen(serv_socket,5);
    if(res<0)
    {
        printf("listen error!\n");
        return -1;
    }
    // 定义客户端sock_addr_in结构体
    struct sockaddr_in clientaddr;
    int len_client_addr=sizeof(clientaddr);
    
    int shm_id=get_shm_id(4095);
    char* shm = (char *)shmat(shm_id, NULL, 0);
    memset(shm,0,4095);
    
    while(1)
    {
        int clientfd=accept(serv_socket, (struct sockaddr*) &clientaddr,&len_client_addr);
        // printf("%d",clientaddr.sin_addr.s_addr);
        connect_info.connectfd=clientfd;
        connect_info.client_addr=clientaddr;
       
        pid_t fpid=fork();
        if(fpid==0)
        {
            print_msg(&connect_info);
            break;

        }else
        {
            printf("created\n");
        }
    }
    close(res);

}

int check_and_send(int user_shm_id,char* data_buf)
{
    // int shm_id=get_shm_id(4095);
    // char* shm = (char *)shmat(shm_id, NULL, 0);
    // printf("\ncheck %d ",user_id);
    // int user_shm_id=get_user_shm_id(1024,user_id);
    printf("\ncheck %d ",user_shm_id);
    char* user_shm = (char *)shmat(user_shm_id, NULL, 0);
    printf("%p ",user_shm);
    memcpy(user_shm,data_buf,1024);
    printf("^%s ",user_shm);
    // memcpy(user_shm,data_buf,strlen(data_buf));
    
    
    // struct Connect_Info* last_shm=(struct Connect_Info*)shm;
    // while (last_shm->next_connect_info!=NULL)
    // {
    //     printf("--%s -%s-",last_shm->next_connect_info->username,username);
    //     if(strcmp(last_shm->next_connect_info->username,username)==0)
    //     {
            
    //         printf("-%s--",username);
    //         ssize_t wd=write(last_shm->next_connect_info->connectfd,data_buf,strlen(data_buf)+1);
    //     }
    //     last_shm=last_shm->next_connect_info;
    // }
    return 1;            
}


int write_socket(struct Connect_Info* connect_info)
{
    
    printf("username:%s ",connect_info->username);
    // int user_shm_id=get_user_shm_id(1024,connect_info->user_id);
    // char* user_shm = (char *)shmat(user_shm_id, NULL, 0);
    printf("user_shm_id:%d ",connect_info->user_shm_id);
    char* user_shm = (char *)shmat(connect_info->user_shm_id, NULL, 0);
    int i=0;
    while(1)
    {   
        // 为什么需要pritnf,才能正常运行
        // printf("."); 
        printf("%s",user_shm);
            
        if(strlen(user_shm)>0)
        {
            ssize_t wd=write(connect_info->connectfd,user_shm,strlen(user_shm));
            // wd=write(connect_info->connectfd,"recieved"+0,9);
            memset(user_shm,0,1024);
            printf("wd is %d ",wd);
        }
        
    }
    return 0;
    
}

int print_msg(struct Connect_Info* connect_info)
{
    char recv_buf[1024];  
    char send_buf[1024];
    bool login_status=false;


    struct USER_PASSWD user_info;
    // 验证登录是否成功 
    do
    {
        
        ssize_t rd=read(connect_info->connectfd,recv_buf,1024);
        if(rd<0)
        {
            printf(" client is offline !\n");
        }
        
        memset(&user_info,0,sizeof(user_info));
        memcpy(&user_info,recv_buf,sizeof(user_info));
        printf("%s %s",user_info.username,user_info.password);
        login_status=check_user_passwd(&user_info);
        // printf("\nstatus is %d",login_status);
        if(login_status)
        {
            memset(send_buf,0,1024);
            memcpy(send_buf,"#@01",4);
            
            ssize_t rw=write(connect_info->connectfd,send_buf,strlen(send_buf)+1);
            printf("\n%s is logined ",user_info.username);
            
            int shm_id=get_shm_id(4095);
            char* shm = (char *)shmat(shm_id, NULL, 0);
            
            int user_id=get_id_by_username(user_info.username);
            connect_info->user_id=user_id;
            printf("%d ",user_id);
            
            int user_shm_id=get_user_shm_id(1024,connect_info->user_id);
            char* user_shm = (char *)shmat(user_shm_id, NULL, 0);
            memset(user_shm,0,1024);
            printf("%d ",user_shm_id);

            connect_info->user_shm_id=user_shm_id;
            memcpy(connect_info->username,user_info.username,lenght_of_username);
            
            add_connect_info(connect_info,shm); 
            printf("username is %s ",connect_info->username);
            // memcpy(shm,connect_info,sizeof(struct Connect_Info));

        }else
        {
            memset(send_buf,0,1024);
            memcpy(send_buf,"#@02",4);
            ssize_t rw=write(connect_info->connectfd,send_buf,strlen(send_buf)+1);   
            printf("%s username or password error\n",user_info.username);
        }
    }while(!login_status);
    
    
    // 创建线程   
    pthread_t tid;
    pthread_create(&tid,NULL,write_socket,connect_info);
    // pthread_join(tid,NULL);

    int i=0;
    // 登录成功后，接受客户端数据
    while (1)
    {        
        
        // printf("username:%s ",connect_info->username);
        // // int user_shm_id=get_user_shm_id(1024,connect_info->user_id);
        // // char* user_shm = (char *)shmat(user_shm_id, NULL, 0);
        // printf("user_shm_id:%d ",connect_info->user_shm_id);
        // char* user_shm = (char *)shmat(connect_info->user_shm_id, NULL, 0);
        // printf("user_shm:%s ",user_shm);
        // ssize_t wd=write(connect_info->connectfd,user_shm,strlen(user_shm));
        // // wd=write(connect_info->connectfd,"recieved"+0,9);
        // printf("wd is %d ",wd);
        // memset(user_shm,0,1024);  
        // memset(recv_buf,0,1024);
        // if(strlen(user_shm)>0)
        // {
        //     printf("send data:%s",user_shm);
        //     ssize_t wd=write(connect_info->connectfd,user_shm,strlen(user_shm));
        //     // memset(user_shm,0,1024);
        // }
        ssize_t rd=read(connect_info->connectfd,recv_buf,1024);
        if(rd<=0)
        {
            printf("%s client is offline !\n",connect_info->username);
            int shm_id=get_shm_id(4095);
            char* shm = (char *)shmat(shm_id, NULL, 0);
            
            memcpy(connect_info->username,user_info.username,lenght_of_username);
            del_connect_info(connect_info,shm); 

            close(connect_info->connectfd);
            break;
        }
        printf("\nthe count of recv data %d ",rd);
        struct Message_Header message_header;
        memcpy(&message_header,recv_buf,sizeof(struct Message_Header));
        // memcpy(&message_header.n_people,recv_buf+lenght_of_username,sizeof(int));
        printf("\nusername and n_people %s %d ",message_header.username,message_header.n_people);
        char to_whos[message_header.n_people*lenght_of_username];
        memcpy(to_whos,recv_buf+sizeof(struct Message_Header),message_header.n_people*lenght_of_username);
       
        char show_to_whos[message_header.n_people*lenght_of_username];
        char* tmp_show=show_to_whos;
        char* tmp_data=recv_buf+sizeof(struct Message_Header)+message_header.n_people*lenght_of_username;
            
        for(int i=0;i<sizeof(to_whos)/lenght_of_username;i++)
        {
            char tmp_to_who[lenght_of_username];
            memcpy(tmp_to_who,to_whos+i*lenght_of_username,lenght_of_username);
            printf("\nwho and data:%s,%s ",tmp_to_who,tmp_data);

            int shm_id=get_shm_id(4095);
            char* shm = (char *)shmat(shm_id, NULL, 0);
            
            int tmp_user_shm_id=get_user_shm_id_by_name(tmp_to_who);
            if(tmp_user_shm_id!=0)     check_and_send(tmp_user_shm_id,tmp_data);
            printf("tmp_user_shm_id %d ",tmp_user_shm_id);
            // printf("%s\n",to_whos+i*lenght_of_username);
            memcpy(tmp_show,to_whos+i*lenght_of_username,strlen(to_whos+i*lenght_of_username));
            tmp_show=tmp_show+strlen(to_whos+i*lenght_of_username);
            
            if(i<sizeof(to_whos)/lenght_of_username-1)
            {
                memcpy(tmp_show,",",1);
                tmp_show++;
        
            }  
        }
        
        printf("\nMessage from %s to %s:%s\n",user_info.username,show_to_whos,tmp_data);
        
    }
    close(connect_info->connectfd);

    return 1;
}